package org.jpropelleralt.jview.list.impl;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JPanel;

import org.jpropelleralt.box.Box;
import org.jpropelleralt.change.Change;
import org.jpropelleralt.jview.JView;
import org.jpropelleralt.list.ListBox;
import org.jpropelleralt.plumbing.Source;
import org.jpropelleralt.plumbing.Target;
import org.jpropelleralt.ref.Ref;

import com.jgoodies.forms.builder.DefaultFormBuilder;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;

/**
 * A {@link JView} showing one or more of {@link ListAddAction}, {@link ListDeleteAction},
 * {@link ListMoveAction}s for up/down, as {@link JButton}s in a {@link JPanel}. 
 * @param <T>		The type of element in the {@link ListBox} 
 */
public class ListButtonsView<T> implements JView {

	private final JPanel panel;
	
	private ListButtonsView(
			Ref<ListBox<T>> list, 
			Ref<Integer> selectionIndex, 
			Ref<Boolean> locked, 
			Source<T> source, 
			Target<T> target,
			boolean add,
			boolean delete,
			boolean move) {
		List<JButton> buttons = new LinkedList<JButton>();
		if (add) {
			ListAddAction<T> addAction = ListAddAction.create(list, selectionIndex, source, locked);
			buttons.add(new JButton(addAction));
		}
		if (delete) {
			ListDeleteAction<T> deleteAction = ListDeleteAction.create(list, selectionIndex, target, locked);
			buttons.add(new JButton(deleteAction));
		}
		if (move) {
			ListMoveAction<T> moveUpAction = ListMoveAction.createUpAction(list, selectionIndex, locked);
			ListMoveAction<T> moveDownAction = ListMoveAction.createDownAction(list, selectionIndex, locked);
			buttons.add(new JButton(moveUpAction));
			buttons.add(new JButton(moveDownAction));
		}
		if (buttons.isEmpty()) {
			throw new IllegalArgumentException("Can't create ListButtonsView with add, delete and move all false");
		}
		
		String colSpec = "fill:0dlu:grow, ";
		for (int i = 0; i < buttons.size() - 1; i++) {
			colSpec += "pref, 3dlu, ";
		}
		colSpec += "pref, fill:0dlu:grow";
		
		FormLayout layout = new FormLayout(colSpec, "pref");
		for (int i = 0; i < buttons.size(); i++) {
			layout.addGroupedColumn(2+2*i);
		}
		DefaultFormBuilder builder = new DefaultFormBuilder(layout);
		CellConstraints cc = new CellConstraints();
		
		for (int i = 0; i < buttons.size(); i++) {
			builder.add(buttons.get(i), cc.xy(2+2*i, 1));
		}
		
		panel = builder.getPanel();
	}
	
	/**
	 * Create a {@link ListButtonsView}
	 * @param <T>				The type of element in the {@link ListBox} 
	 * @param list				The {@link ListBox}, as a {@link Ref}
	 * @param selectionIndex	The selection index, as a {@link Ref}
	 * @param locked			While this is true, buttons will not edit. 
	 * @param source 			{@link Source} for elements to add to list.
	 * @param target 			{@link Target} for elements removed from list, or null if this is not required.
	 * @param add 				True to have a {@link ListAddAction} button.
	 * @param delete 			True to have a {@link ListDeleteAction} button.
	 * @param move 				True to have {@link ListMoveAction} buttons to move up and down.
	 * @return 					A new {@link ListButtonsView}
	 */
	public static <T> ListButtonsView<T> create(
			Ref<ListBox<T>> list, 
			Ref<Integer> selectionIndex, 
			Ref<Boolean> locked, 
			Source<T> source, 
			Target<T> target,
			boolean add,
			boolean delete,
			boolean move) {
		return new ListButtonsView<T>(list, selectionIndex, locked, source, target, add, delete, move);
	}
	
	/**
	 * Create a {@link ListButtonsView} with add, delete and move buttons
	 * @param <T>				The type of element in the {@link ListBox} 
	 * @param list				The {@link ListBox}, as a {@link Ref}
	 * @param selectionIndex	The selection index, as a {@link Ref}
	 * @param locked			While this is true, buttons will not edit. 
	 * @param source 			{@link Source} for elements to add to list.
	 * @param target 			{@link Target} for elements removed from list, or null if this is not required.
	 * @return 					A new {@link ListButtonsView}
	 */
	public static <T> ListButtonsView<T> create(
			Ref<ListBox<T>> list, 
			Ref<Integer> selectionIndex, 
			Ref<Boolean> locked, 
			Source<T> source, 
			Target<T> target) {
		return create(list, selectionIndex, locked, source, target, true, true, true);
	}
	
	@Override
	public Format format() {
		return Format.LARGE;
	}

	@Override
	public JComponent getComponent() {
		return panel;
	}

	@Override
	public boolean selfNaming() {
		//No need for any extra naming
		return true;
	}

	@Override
	public void changes(Map<Box, Change> changes) {
		//Subviews will update themselves
	}
	@Override
	public void update() {
		//Subviews will update themselves
	}
}
